#include <iostream>
#include <string>
#include <cstdio>
#include <stdlib.h>
#include <vector>
#include <thread>
#include <pthread.h>
#include <unistd.h>

// void *threadRun(void *args)
// {
//     int cnt = 10;
//     while(cnt)
//     {
//         // 每隔一秒打印一次
//         std::cout << "new thread run...,cnt: " << cnt-- << std::endl;
//         sleep(1);
//     }
//     return nullptr;
// }

// 10进制打印tid
void PrintToDec(pthread_t &tid)
{
    std::cout << "tid: " << tid << std::endl;
}

// 16进制打印tid
std::string PrintToHex(pthread_t &tid)
{
    char buffer[128];
    snprintf(buffer, sizeof(buffer), "0x%lx", tid);
    return buffer;
}

// int main()
// {
//     pthread_t tid;
//     // 问题1 : main 和 new 线程谁先运行？ 不确定
//     // 创建新线程
//     int n = pthread_create(&tid, nullptr, threadRun, (void *)"thread 1");
//     if (n != 0) // 后面暂时不关心
//     {
//         std::cerr << "create thread errno " << std::endl;
//         return 1;
//     }
//     // 问题3 : tid是什么样子的？是什么呢？虚拟地址！ 为什么？
//     PrintToDec(tid); // 按照10进制方式打印
//     std::string tid_str = PrintToHex(tid); // 按照16进制方式打印
//     std::cout << "tid: " << tid_str << std::endl;

//     std::cout << "main thread join begin..." << std::endl;
//     // 问题2 : 我们期望谁最后退出？ main thread , 你如何保证呢？
//     // 等待新线程终止
//     n = pthread_join(tid,nullptr); // join来保证。 不join呢？主线程活着，新线程退出会造成类似僵尸问题
//     if(n == 0)
//     {
//         std::cout << "main thread wait success " << std::endl;
//     }
//     return 0;
// }

// 可以给线程传多个参数，甚至方法了
// class ThreadData
// {
// public:
//     std::string name;
//     int num;
// };

// void *threadRun(void *args)
// {
//     // std::string name = (const char*)args;
//     // int a = *(int*)args;// warning 系统为64位，指针大小为8字节，int为4字节
//     ThreadData* td = static_cast<ThreadData*>(args); // 安全类别强转 (ThreadData*)args

//     int cnt = 10;
//     while(cnt)
//     {
//         // 每隔一秒打印一次
//         // std::cout << name << " run...,cnt: " << cnt-- << std::endl;
//         // std::cout << a << " run...,cnt: " << cnt-- << std::endl;
//         std::cout << td->name << " run...,num is " << td->num << ",cnt: " << cnt-- << std::endl;
//         sleep(1);
//     }
//     std::cout << "delete td:" << td << std::endl;
//     delete td; // 释放空间
//     return nullptr;
// }

// int main()
// {
//     pthread_t tid;
//     // 问题4 : 全面看待线程函数传参 : 我们可以传递任意类型，但你一定要能想得起来，也能传递类对象地址！！
//     // int a = 100;
//     // int n = pthread_create(&tid, nullptr, threadRun, (void *)&a);

//     // 不推荐
//     // ThreadData td;
//     // td.name = "thread-1";
//     // td.num = 1;
//     // int n = pthread_create(&tid, nullptr, threadRun, (void*)&td); // 传递线程结构体对象

//     // // 再创建一个新线程，使用同一个局部变量，修改值两个都修改了
//     // td.name = "thread-2";
//     // td.num = 2;
//     // n = pthread_create(&tid, nullptr, threadRun, (void*)&td); // 传递线程结构体对象

//     ThreadData* td = new ThreadData();
//     td->name = "thread-1";
//     td->num = 1;
//     int n = pthread_create(&tid, nullptr, threadRun, td);

//     // int n = pthread_create(&tid, nullptr, threadRun, (void *)"thread 1");
//     if (n != 0) // 后面暂时不关心
//     {
//         std::cerr << "create thread errno " << std::endl;
//         return 1;
//     }
//     std::string tid_str = PrintToHex(tid); // 按照16进制方式打印出来
//     std::cout << "tid: " << tid_str << std::endl;

//     std::cout << "main thread join begin..." << std::endl;
//     // 等待新线程终止
//     n = pthread_join(tid,nullptr);
//     if(n == 0)
//     {
//         std::cout << "main thread wait success " << std::endl;
//     }
//     return 0;
// }

// 问题5 : 如何全面看待线程函数返回 :
//  a.只考虑正确的返回，不考虑异常，因为异常了，整个进程就崩溃了，包括主线程
//  b.我们可以传递任意类型，但你一定要能想得起来，也能传递类对象地址！！
//  void *threadRun(void *args)
//  {
//      ThreadData* td = static_cast<ThreadData*>(args); // 安全类别强转 (ThreadData*)args
//      int cnt = 10;
//      while(cnt)
//      {
//          std::cout << td->name << " run...,num is " << td->num << ",cnt: " << cnt-- << std::endl;
//          // int* p = nullptr;
//          // *p = 100; // 故意野指针
//          sleep(1);
//      }
//      std::cout << "delete td:" << td << std::endl;
//      delete td; // 释放空间
//      return (void*)111;
//  }

// int main()
// {
//     pthread_t tid;

//     ThreadData* td = new ThreadData();
//     td->name = "thread-1";
//     td->num = 1;
//     int n = pthread_create(&tid, nullptr, threadRun, td);

//     std::cout << "main thread join begin..." << std::endl;
//     // 等待新线程终止
//     void* code = nullptr; // 开辟了空间的！！！
//     n = pthread_join(tid,&code);
//     if(n == 0)
//     {
//         // 主线程拿新线程的退出信息，int会有精度损失，Linux中地址8字节，int4字节
//         std::cout << "main thread wait success, new thread exit code: " << (uint64_t)code << std::endl;
//     }
//     return 0;
// }

// class ThreadData
// {
// public:
//     int Excute()
//     {
//         return x + y;
//     }
// public:
//     std::string name;
//     int x;
//     int y;
// };

// class ThreadResult
// {
// public:
//     std::string Print()
//     {
//         return std::to_string(x) + "+" + std::to_string(y) + "=" + std::to_string(result);
//     }
// public:
//     int x;
//     int y;
//     int result;
// };

// // b.我们可以传递任意类型，但你一定要能想得起来，也能传递类对象地址！！
// void *threadRun(void *args)
// {
//     ThreadData* td = static_cast<ThreadData*>(args);
//     int cnt = 10;
//     ThreadResult* result = new ThreadResult();
//     while(cnt)
//     {
//         sleep(3);
//         std::cout << td->name << " run...,cnt: " << cnt-- << std::endl;
//         result->result = td->Excute();
//         result->x = td->x;
//         result->y = td->y;
//        break;
//     }
//     std::cout << "delete td:" << td << std::endl;
//     delete td; // 释放空间
//     return (void*)result;
// }

// int main()
// {
//     pthread_t tid;

//     ThreadData* td = new ThreadData();
//     td->name = "thread-1";
//     td->x = 10;
//     td->y = 20;
//     int n = pthread_create(&tid, nullptr, threadRun, td);

//     std::cout << "main thread join begin..." << std::endl;
//     // 等待新线程终止
//     ThreadResult* result = nullptr; // 开辟了空间的！！！
//     n = pthread_join(tid,(void**)&result);
//     if(n == 0)
//     {
//         std::cout << "main thread wait success, new thread exit code: " << result->Print() << std::endl;
//     }
//     return 0;
// }

// const int num = 10;

// void *threadrun(void *args)
// {
//     std::string name = static_cast<const char *>(args);
//     while (true)
//     {
//         // 打印的线程名是乱的，线程执行顺序是不确定的，
//         // 且因为在名字栈区for循环内部创建，每切换一个线程，名字就会被覆盖，有问题！！！
//         std::cout << name << " is running" << std::endl;
//         sleep(1);
//         break;
//     }
//     // return nullptr;
//     return args;
// }

// int main()
// {
//     // 问题6 : 如何创建多线程呢？
//     std::vector<pthread_t> tids;
//     for (int i = 0; i < num; i++)
//     {
//         // 1.有线程的id
//         pthread_t tid;
//         // 2.有线程的名字(错误示范)
//         // char name[128];
//         // snprintf(name, sizeof(name), "thread-%d", i + 1);

//         // 2.有线程的名字(正确示范)
//         char* name  = new char[128];
//         snprintf(name, 128, "thread-%d", i + 1);
//         pthread_create(&tid, nullptr, threadrun, /*线程的名字*/ name);

//         // 3.保存所有线程的id信息
//         tids.emplace_back(tid);
//     }
//     // join todo
//     for(auto tid : tids)
//     {
//         void* name = nullptr;
//         pthread_join(tid,&name);
//         // std::cout << PrintToHex(tid) << " quit" << std::endl;
//         std::cout << (const char*)name << " quit" << std::endl;
//         delete (const char*)name;
//     }
//     // sleep(100);
//     return 0;
// }

// const int num = 10;

// void *threadrun(void *args)
// {
//     std::string name = static_cast<const char *>(args);
//     // 死循环
//     while (true)
//     {
//         std::cout << name << " is running" << std::endl;
//         sleep(1);
//         // break; // 1秒后退出循环
//     }
//     // return args;
//     // exit(1); // 进程: 专门用来终止进程的，不能终止线程
//     pthread_exit(args); // 专门终止一个线程的！
// }

// // main函数结束: main thread 结束，表示进程结束！
// int main()
// {
//     // 问题7 : 新线程如何终止
//     // 1.线程函数 return
//     // 2.pthread_exit
//     // 3.main thread call pthread_cancel，新线程退出结果是-1
//     std::vector<pthread_t> tids;
//     for (int i = 0; i < num; i++)
//     {
//         // 1.有线程的id
//         pthread_t tid;
//         // 2.有线程的名字(正确示范)
//         char* name  = new char[128];
//         snprintf(name, 128, "thread-%d", i + 1);
//         pthread_create(&tid, nullptr, threadrun, /*线程的名字*/ name);
//         // 3.保存所有线程的id信息
//         tids.emplace_back(tid);
//     }
//     sleep(1);
//     // join todo
//     for(auto tid : tids)
//     {
//         pthread_cancel(tid); // 取消新线程
//         std::cout << "cancel: " << PrintToHex(tid) << std::endl;
//         void* result = nullptr; // 线程被取消线程的退出结果是：-1 #define PTHREAD_CANCELED ((void *) -1)
//         pthread_join(tid,&result);
//         std::cout << (long long int)result << " quit" << std::endl;
//     }
//     // join todo
//     // for(auto tid : tids)
//     // {
//     //     void* name = nullptr;
//     //     pthread_join(tid,&name);
//     //     std::cout << (const char*)name << " quit" << std::endl;
//     //     delete (const char*)name;
//     // }
//     // 主线程不退
//     sleep(100);
//     return 0;
// }

// 问题8: 可不可以不join线程，让它执行完就退出呢？可以！detach分离
// a. 一个线程被创建，默认是joinable的，必须要被join的.
// b. 如果一个线程被分离，线程的工作状态分离状态，不须要/不能被join的. 依旧属于进程内部，但是不需要被等待了
// const int num = 10;

// void *threadrun(void *args)
// {
//     // pthread_detach(pthread_self());
//     std::string name = static_cast<const char *>(args);
//     while (true)
//     {
//         std::cout << name << " is running" << std::endl;
//         sleep(1);
//         break; 
//     }
//     pthread_exit(args); 
// }

// int main()
// {
//     std::vector<pthread_t> tids;
//     for (int i = 0; i < num; i++)
//     {
//         pthread_t tid;
//         char* name  = new char[128];
//         snprintf(name, 128, "thread-%d", i + 1);
//         pthread_create(&tid, nullptr, threadrun, /*线程的名字*/ name);
//         tids.emplace_back(tid);
//     }
//     for(auto tid : tids)
//     {
//         pthread_detach(tid);// 主线程分离新线程，前提新线程需要存在
//     }

//     // 做我的事情
//     // while(true)
//     // {
//     //     sleep(1);
//     // }
//     // sleep(1);
//     // 分离后无需join
//     for(auto tid : tids)
//     {
//         void* result = nullptr;
//         int n = pthread_join(tid,&result);
//         std::cout << (long long int)result << " quit...,n: " << n << std::endl;
//     }
//     // 主线程不退
//     //sleep(100);
//     return 0;
// }

void threadrun(std::string name,int num)
{
    while(num)
    {
        std::cout << name << " num : " << num<< std::endl;
        num--;
        sleep(1);
    }
}

int main()
{
    std::string name = "thread-1";
    std::thread mythread(threadrun,name,10); // 创建线程
    while(true)
    {
        std::cout << "main thhread..." << std::endl;
        sleep(1);
    }
    mythread.join(); // 终止线程
    return 0;
}